<template>
  <div class="home">
      <ul>
        <li v-for="item in cars" :key="item.id">
          <input type="checkbox" v-model="item.check">
          <div class="content-detail">
            <img :src="item.img" alt="">
            <div>
              <h3>{{item.name}}</h3>
              <span>{{item.desc}}</span>
              <section class="step">
                <span @click="menus(item)">-</span><span>{{item.num}}</span><span @click="add(item)">+</span>
              </section>
              <div class="price-box">
                <span>{{item.price}}</span>
                <section>
                  <span>￥{{item.price*item.num}}</span>
                  <button @click="del(item.id)">删除</button>
                </section>
              </div>
            </div>
          </div>
        </li>
      </ul>
      <div>
        <span>总计：{{sumPrice}}</span>
        <button @click="checkAll(true)">全选</button><button @click="checkAll(false)">全不选</button><button @click="checkOther">反选</button><button @click="delCheck">选中删除</button><button @click="checkBtn"><input type="checkbox" :checked="check">全选</button>
      </div>
  </div>
</template>

<script>
import { ref, reactive, defineComponent, onMounted, toRefs, watch, computed } from 'vue'
// defineComponent 定义一个组件 返回值时传入的对象 对象可以配置vue组件的相关属性
// defineComponent 参数也可以是一个函数 函数的名可以作为组件名使用 函数就相当于一个setup
import axios from 'axios'
export default defineComponent({
  name: 'Home',
  setup() {
    // reactive 主要用来声明具有响应式的数组或者对象（复杂数据类型）
    let state = reactive({
      cars: []
    })

    // 标记全选是否勾中的数据
    let check = ref(false)

    // 组件渲染完成后
    onMounted(() => {
      axios.get('/carList.json').then(res => {
        // console.log(res);
        state.cars = res.data
      })
    });

    // 点击减号减少数量的函数
    function menus(item) {
      if(item.num > 1) {
        item.num--
      }
    }

    // 添加数量的函数
    function add(item) {
      item.num++
    }

    // 点击全选按钮触发的函数
    function checkAll(bool) {
      state.cars.forEach(item => {
        item.check = bool
      })
    }

    // 反选的逻辑
    function checkOther() {
      state.cars.forEach(item => {
        item.check = !item.check
      })
    }

    // 选中删除的逻辑
    function delCheck() {
      state.cars = state.cars.filter(item => {
        return !item.check
      })
    }

    // 单个删除数据的逻辑
    function del(id) {
      state.cars = state.cars.filter(item => {
        return item.id != id
      })
    }

    // 带有勾选框的按钮全选逻辑
    function checkBtn() {
      check.value = !check.value
      state.cars.forEach(item => {
        item.check = check.value
      })
    }

    // 监听数据变化 watch 第一个参数是要监听的数据 第二个数据变化后的回调函数 ，第三个是配置项
    // 如果监听的是ref数据则可以直接监听 但是如果兼容一个reactive数据变化则要用一个函数返回监听的数据
    watch(() => state.cars, (to, from) => {
      // console.log(to);
      let flag = false
      to.forEach(item => {
        if(!item.check) {
          flag = true  // flag是true表示至少有一个商品未被选中
        }
      })
      if(flag) {
        check.value = false
      } else {
        check.value = true
      }
    }, {
      deep:true
    })

    // 计算属性 用来计算所有选中的商品的价格
    let sumPrice = computed(() => {
      let num = 0
      state.cars.forEach(item => {
        if(item.check) {
          num += item.price*item.num
        }
      })
      return num
    })
    
    // 页面用想要使用这里声明的数据或者函数 比如先返回出去
    // toRefs 返回一个对象 并将对象中的每一个属性都做成了一个ref数据
    return {
      ...toRefs(state),
      check,
      sumPrice,
      menus,
      add,
      checkAll,
      checkOther,
      delCheck,
      del,
      checkBtn
    }
  }
}) 
</script>
<style lang="scss" scoped>
  ul {
    list-style: none;
    margin: 0;
    padding: 0;
  }
  li {
    display: flex;
    align-items: center;
    padding: 15px 0;
    img {
      width: 80px;
      height: 80px;
      border-radius: 6px;
      display: block;
      margin: 0 15px;
    }
    h3 {
      margin: 0;
    }
    .content-detail {
      display: flex;
      .step {
        display: flex;
        span {
          width: 20px;
          height: 20px;
          line-height: 20px;
          text-align: center;
          background-color: #eee;
          border: 1px solid #ccc;
        }
      }
    }
    .price-box {
      display: flex;
      width: 220px;
      justify-content: space-between;
      align-items: center;
    }
  }
  
</style>
